package com.unswift.cloud.service;

import java.lang.annotation.Annotation;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.api.ApiHandle;
import com.unswift.cloud.adapter.system.api.SystemApiInterfacesAdapter;
import com.unswift.cloud.adapter.system.api.SystemApiInterfacesRecordAdapter;
import com.unswift.cloud.adapter.system.api.SystemApiParamAdapter;
import com.unswift.cloud.enums.system.api.InterfacesParamCategoryEnum;
import com.unswift.cloud.pojo.bo.system.api.interfaces.SystemApiInterfacesCreateBo;
import com.unswift.cloud.pojo.bo.system.api.interfaces.SystemApiInterfacesDeleteBo;
import com.unswift.cloud.pojo.bo.system.api.interfaces.SystemApiInterfacesTreeBo;
import com.unswift.cloud.pojo.bo.system.api.interfaces.SystemApiInterfacesUpdateBo;
import com.unswift.cloud.pojo.bo.system.api.interfaces.SystemApiInterfacesViewBo;
import com.unswift.cloud.pojo.bo.system.api.interfaces.record.SystemApiInterfacesRecordCreateBo;
import com.unswift.cloud.pojo.dao.sql.Sql;
import com.unswift.cloud.pojo.dao.system.api.interfaces.SystemApiInterfacesDataDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.SystemApiInterfacesDeleteDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.SystemApiInterfacesInsertBatchItemDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.SystemApiInterfacesInsertDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.SystemApiInterfacesSearchDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.SystemApiInterfacesSingleDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.SystemApiInterfacesUpdateDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.record.SystemApiInterfacesRecordDataDo;
import com.unswift.cloud.pojo.dao.system.api.interfaces.record.SystemApiInterfacesRecordInsertDo;
import com.unswift.cloud.pojo.dto.BaseDto;
import com.unswift.cloud.pojo.vo.system.api.interfaces.SystemApiInterfacesCreateVo;
import com.unswift.cloud.pojo.vo.system.api.interfaces.SystemApiInterfacesDeleteVo;
import com.unswift.cloud.pojo.vo.system.api.interfaces.SystemApiInterfacesProgressVo;
import com.unswift.cloud.pojo.vo.system.api.interfaces.SystemApiInterfacesSynchVo;
import com.unswift.cloud.pojo.vo.system.api.interfaces.SystemApiInterfacesTreeVo;
import com.unswift.cloud.pojo.vo.system.api.interfaces.SystemApiInterfacesUpdateVo;
import com.unswift.cloud.pojo.vo.system.api.interfaces.SystemApiInterfacesViewVo;
import com.unswift.cloud.pojo.vo.system.api.interfaces.record.SystemApiInterfacesRecordCreateVo;
import com.unswift.cloud.pojo.vo.system.api.param.SystemApiParamTreeVo;
import com.unswift.cloud.pojo.vo.system.api.param.SystemApiParamViewVo;
import com.unswift.cloud.queue.IQueueTaskHandle;
import com.unswift.cloud.queue.LocalSecurityQueue;
import com.unswift.cloud.queue.QueueTask;
import com.unswift.exception.CoreException;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.JsonUtils;
import com.unswift.utils.ObjectUtils;

@Service
@Api(value="接口api服务", author="unswift", date="2023-09-05", version="1.0.0")
public class SystemApiInterfacesService extends BaseService implements IQueueTaskHandle<BaseDto>{
	
	@Autowired
	@ApiField("接口api公共服务")
	private SystemApiInterfacesAdapter systemApiInterfacesAdapter;
	
	@Autowired
	@ApiField("接口api属性公共服务")
	private SystemApiParamAdapter systemApiParamAdapter;
	
	@Autowired
	@ApiField("接口api访问记录公共服务")
	private SystemApiInterfacesRecordAdapter systemApiInterfacesRecordAdapter;
	
	@Autowired
	@ApiField("api处理类")
	private ApiHandle apiHandle;
	
	@Autowired
	@ApiField("本服务队列")
	private LocalSecurityQueue localSecurityQueue;
	
	@ApiField("微服务名称")
	@Value("${spring.application.name}")
	private String serverName;
	
	@ApiField("是否又任务执行")
	private Boolean isHaveTask=false;
	
	@ApiField("错误消息，如果发生异常")
	private String errorMessage;
	
	@ApiField("执行进度，0-100")
	private Integer progress=0;
	
	@ApiMethod(value="查询接口api树", params=@ApiField("查询条件"), returns=@ApiField("包含查询数据的分页对象"))
	public SystemApiInterfacesTreeVo findTree(SystemApiInterfacesTreeBo searchBo){
		SystemApiInterfacesSearchDo search=this.convertPojo(searchBo, SystemApiInterfacesSearchDo.class);//将Bo转换为Do
		search.setServer(serverName);
		Sql sql=Sql.createSql();
		sql.addOrderBy("sort_", Sql.ORDER_BY_ASC);;
		search.setSql(sql);
		List<SystemApiInterfacesDataDo> dataList=systemApiInterfacesAdapter.findList(search);//将Do转换为Vo
		SystemApiInterfacesTreeVo tree=new SystemApiInterfacesTreeVo(0L, "接口API", "catalog", true, false);
		if(ObjectUtils.isNotEmpty(dataList)) {
			List<SystemApiInterfacesDataDo> rootDataList=dataList.stream().filter(i -> ObjectUtils.isEmpty(i.getParentId())).collect(Collectors.toList());//查找跟节点
			List<SystemApiInterfacesDataDo> childrenDataList=dataList.stream().filter(i -> ObjectUtils.isNotEmpty(i.getParentId())).collect(Collectors.toList());//查找孩子节点
			List<Long> noFindParentIdList=childrenDataList.stream().filter(c -> !rootDataList.stream().filter(r -> r.getId().equals(c.getParentId())).findAny().isPresent()).map(c -> c.getParentId()).distinct().collect(Collectors.toList());//匹配没有查询出跟节点的节点
			if(ObjectUtils.isNotEmpty(noFindParentIdList)) {
				List<SystemApiInterfacesDataDo> noFindParentList=systemApiInterfacesAdapter.findByIds(noFindParentIdList);
				rootDataList.addAll(noFindParentList);
			}
			List<SystemApiInterfacesTreeVo> rootTreeNodeList=rootDataList.stream().sorted(Comparator.comparing(i -> ObjectUtils.init(i.getSort(), 0))).map(r -> new SystemApiInterfacesTreeVo(r.getId(), r.getName(), r.getType())).collect(Collectors.toList());
			for (SystemApiInterfacesTreeVo rootTreeNode : rootTreeNodeList) {
				rootTreeNode.setChildren(childrenDataList.stream().filter(r -> r.getParentId().equals(rootTreeNode.getId())).map(r -> 
					ObjectUtils.isNotEmpty(searchBo.getSelectNodeId()) && r.getId().equals(searchBo.getSelectNodeId())?
						new SystemApiInterfacesTreeVo(r.getId(), r.getName(), r.getType(), false, true):
						new SystemApiInterfacesTreeVo(r.getId(), r.getName(), r.getType())
				).collect(Collectors.toList()));
				if(rootTreeNode.getChildren().stream().filter(c -> c.getChecked()).findAny().isPresent()) {//如果有子节点被选中，则展开父节点
					rootTreeNode.setSpread(true);
				}
			}
			tree.setChildren(rootTreeNodeList);
		}
		return tree;
	}
	
	@ApiMethod(value="查询接口api详情", params=@ApiField("详情业务实体，包含id字段"), returns=@ApiField("接口api详情数据"))
	public SystemApiInterfacesViewVo view(SystemApiInterfacesViewBo viewBo){
		SystemApiInterfacesSingleDo search=this.convertPojo(viewBo, SystemApiInterfacesSingleDo.class);
		SystemApiInterfacesDataDo single=systemApiInterfacesAdapter.findSingle(search);
		SystemApiInterfacesViewVo view=this.convertPojo(single, SystemApiInterfacesViewVo.class);
		if(ObjectUtils.isNotEmpty(single)) {
			SystemApiInterfacesDataDo parent=systemApiInterfacesAdapter.findById(single.getParentId());
			view.setParentName(parent.getName());
			view.setPathParamList(this.convertPojoList(systemApiParamAdapter.findByCategoryList(single.getId(), InterfacesParamCategoryEnum.PATH), SystemApiParamViewVo.class));
			view.setUrlParamList(this.convertPojoList(systemApiParamAdapter.findByCategoryList(single.getId(), InterfacesParamCategoryEnum.URL), SystemApiParamViewVo.class));
			view.setFormParamList(this.convertPojoList(systemApiParamAdapter.findByCategoryList(single.getId(), InterfacesParamCategoryEnum.FORM), SystemApiParamViewVo.class));
			List<SystemApiParamTreeVo> bodyParamList = this.convertPojoList(systemApiParamAdapter.findByCategoryList(single.getId(), InterfacesParamCategoryEnum.BODY), SystemApiParamTreeVo.class);
			bodyParamList=systemApiParamAdapter.listToTree(bodyParamList);
			if(ObjectUtils.isNotEmpty(bodyParamList)) {
				view.setBodyParamJson(JsonUtils.toJson(bodyParamList));
			}
			List<SystemApiParamTreeVo> returnParamList = this.convertPojoList(systemApiParamAdapter.findByCategoryList(single.getId(), InterfacesParamCategoryEnum.RETURN), SystemApiParamTreeVo.class);
			returnParamList=systemApiParamAdapter.listToTree(returnParamList);
			if(ObjectUtils.isNotEmpty(returnParamList)) {
				view.setReturnParamJson(JsonUtils.toJson(returnParamList));
			}
			systemApiInterfacesAdapter.setTestInfo(view, bodyParamList);
			SystemApiInterfacesRecordDataDo record=systemApiInterfacesRecordAdapter.findLastByApiInterfaceId(view.getId());
			if(ObjectUtils.isNotEmpty(record)) {
				view.setHeaders(record.getHeaders());
				view.setTestBodyParamJson(record.getBody());
				view.setTestReturnParamJson(record.getResponse());
			}
		}
		return view;
	}

	

	@ApiMethod(value="创建接口api", params=@ApiField("创建的业务实体"), returns=@ApiField("创建结果{0：未创建，1：已创建}"))
	public SystemApiInterfacesCreateVo create(SystemApiInterfacesCreateBo createBo){
		SystemApiInterfacesInsertDo insert=this.convertPojo(createBo, SystemApiInterfacesInsertDo.class);//将Bo转换为Do
		int result=systemApiInterfacesAdapter.save(insert, true);
		return new SystemApiInterfacesCreateVo(result);
	}
	
	@ApiMethod(value="更新接口api", params=@ApiField("更新的业务实体"), returns=@ApiField("更新结果{0：未创建，1：已创建}"))
	public SystemApiInterfacesUpdateVo update(SystemApiInterfacesUpdateBo updateBo){
		SystemApiInterfacesUpdateDo update=this.convertPojo(updateBo, SystemApiInterfacesUpdateDo.class);//将Bo转换为Do
		int result=systemApiInterfacesAdapter.update(update, true);
		return new SystemApiInterfacesUpdateVo(result);
	}
	
	@Transactional("systemTransactionManager")
	@ApiMethod(value="删除接口api", params=@ApiField("删除业务实体，包含id字段"), returns=@ApiField("删除结果{0：未创建，1：已创建}"))
	public SystemApiInterfacesDeleteVo delete(SystemApiInterfacesDeleteBo deleteBo){
		SystemApiInterfacesDeleteDo delete=this.convertPojo(deleteBo, SystemApiInterfacesDeleteDo.class);//将Bo转换为Do
		int result=systemApiInterfacesAdapter.deleteReal(delete);//删除接口
		systemApiInterfacesRecordAdapter.deleteByApiInterfaceId(deleteBo.getId());//删除接口记录
		return new SystemApiInterfacesDeleteVo(result);
	}
	
	@ApiMethod(value="类api同步，把API注解写入数据库", returns=@ApiField("类api详情数据"))
	public SystemApiInterfacesSynchVo synch(){
		if(isHaveTask) {
			throw ExceptionUtils.message("task.is.currently.executing", ExceptionUtils.getMessage("keyword.synchronous"));
		}
		isHaveTask=true;
		progress=1;
		errorMessage=null;
		QueueTask<BaseDto> task=new QueueTask<BaseDto>();
		task.setTaskBean(this);
		task.setTaskData(null);
		localSecurityQueue.offer(task);
		return new SystemApiInterfacesSynchVo(1);
	}
	
	@Override
	@SuppressWarnings("unchecked")
	@Transactional("systemTransactionManager")
	@ApiMethod(value="处理队列任务，生成接口文档并存入数据库", params = @ApiField("传递的参数，此处为null"))
	public void handle(BaseDto data) {
		try {
			List<Class<? extends Annotation>> list = ObjectUtils.asList(Controller.class, RestController.class);
			List<Class<?>> apiControllerList=apiHandle.getApiClassList(list);
			progress=5;
			if(ObjectUtils.isEmpty(apiControllerList)) {
				return ;
			}
			Api apiAnno;
			List<SystemApiInterfacesInsertBatchItemDo> apiFolderList;
			List<SystemApiInterfacesInsertBatchItemDo> apiInterfacesList;
			int index=1, length=apiControllerList.size();
			for (Class<?> apiClass : apiControllerList) {
				apiAnno=apiClass.getAnnotation(Api.class);
				if(!apiAnno.requestApi()) {//不是请求api，则返回
					progress=5+new BigDecimal((index*100.0)/length).setScale(0, RoundingMode.DOWN).intValue();
					index++;
					continue;
				}
				//class
				apiFolderList=systemApiInterfacesAdapter.handleApiAnno(apiAnno, apiClass);
				if(!apiFolderList.get(0).getIsChange()) {//类没有发生变化
					progress=5+new BigDecimal((index*100.0)/length).setScale(0, RoundingMode.DOWN).intValue();
					index++;
					continue;
				}
				//method
				apiInterfacesList = systemApiInterfacesAdapter.handleMethodAnno(apiClass.getDeclaredMethods(), apiFolderList);
				//method params,return
				systemApiParamAdapter.handleInterfaces(apiInterfacesList, apiHandle.getScanPackages());
				//计算进度
				progress=5+new BigDecimal((index*100.0)/length).setScale(0, RoundingMode.DOWN).intValue();
				index++;
			}
		} catch (CoreException e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			errorMessage=e.getMessage();
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			errorMessage=e.getMessage();
			throw e;
		} finally {
			progress=100;
			isHaveTask=false;
		}
	}
	
	@ApiMethod(value="同步接口请求进度方法", returns = @ApiField("接口请求进度实体"))
	public SystemApiInterfacesProgressVo getSynchProgress() {
		if(progress>=100) {
			progress=0;
			String backMessage=errorMessage;
			errorMessage=null;
			return new SystemApiInterfacesProgressVo(100, backMessage);
		}else {
			return new SystemApiInterfacesProgressVo(progress, errorMessage);
		}
	}
	
	@Transactional("systemTransactionManager")
	@ApiMethod(value="保存执行结果", params = @ApiField("执行结果bo"), returns = @ApiField("保存执行结果的结果对象"))
	public SystemApiInterfacesRecordCreateVo createRunningRecord(SystemApiInterfacesRecordCreateBo create) {
		SystemApiInterfacesRecordInsertDo insert=this.convertPojo(create, SystemApiInterfacesRecordInsertDo.class);
		systemApiInterfacesRecordAdapter.save(insert, false);
		
		return new SystemApiInterfacesRecordCreateVo(1);
	}
}